
public class CPU extends Thread
{
	// Access to hardware components
	private IntController hint;
	private Memory mem;
	private Kernel kernel;
	public int[] IR;
	private final int ILEGAL_INST = 1;
	private final int ILEGAL_ACESS = 3;
	private String tabs; 
	public int id; //ID for CPU cause there will be two
	

	CPU(Memory m, Kernel k, IntController i, int iD, String t)
	{
	  hint = i;
	  mem = m;
	  kernel = k;
	  id = iD;
	  tabs = t;
	  IR = new int[4];
	}
	
	public void run()
	{
		Process actual = null;
		
		while (true)
		{
			int SoftINT = 0;
			int HardINT = 0;
			
			// sleep a tenth of a second
			try { sleep(100); }
			catch (InterruptedException e){}
			
			//If no process is executing
			if(actual == null)
			{
				//E a fila ta vazia! 
				if(kernel.readyList.isEmpty())
				{
					System.out.println("Dummy will execute until another process is on readyList");
					kernel.readyList.pushBack(kernel.dummy); //Ponho dummy e espero o console
				}
				actual = kernel.readyList.popFront();
			}	
			else
			{
				// print CPU status to check if it is ok
			    System.out.println(tabs+"CPU" +this.id+ " has process "+ actual.PID + " - PC="+actual.PC +" ");
				SoftINT = fetch(actual);
				if(SoftINT == 0)
				{
					SoftINT = execute_basic_instructions(actual);
					
					if(SoftINT > 0)
						actual = kernel.run(SoftINT, actual);
				}
				else
					actual = kernel.run(SoftINT, actual);
				
			    //Check for Hardware Interrupt and if so call the kernel
			    HardINT = hint.get();
			    if ( HardINT != 0)
			    {
			    	// Call the kernel passing the interrupt number
			    	actual = kernel.run(HardINT,actual);
			    }
			}
			
		}
		
  }
	
	
private int fetch(Process p)
{
	int RD;
	int intNumber = 0;
	int aux = p.BaseRegister + p.PC;
	
	//Le Instr
	//System.out.println("Read from Memory: "+ aux);
	RD = mem.readfromPC(aux,p); //IF RD is neg, them is ILEGAL_ACESS
	//System.out.println("RDDDDDDD "+RD);
    if(RD >= 0)
    {
    	
    	//break the 32bit word into 4 separate bytes
		IR[0] = RD>>>24;
		IR[1] = RD>>>16 & 255;
		IR[2] = RD>>>8 & 255;
		IR[3] = RD & 255; 
    }
    else
    	intNumber = ILEGAL_ACESS;
    
    return intNumber;
}
 		
public int execute_basic_instructions(Process p)
{
	int intNumber = 0;
	if ((IR[0]=='L') && (IR[1]=='M'))
    {
		System.out.println(tabs+"L M "+IR[2]+" "+IR[3]);
		p.reg[IR[2]] = mem.read(IR[3], p);
		p.PC++;
		if(p.reg[IR[2]] < 0)
			intNumber = ILEGAL_ACESS;
    }
	else
	if ((IR[0]=='L') && (IR[1]=='C'))
	{
		System.out.println(tabs+"L C "+IR[2]+" "+IR[3]);
		p.reg[IR[2]] = IR[3];
		p.PC++;
    }
	else
	if ((IR[0]=='W') && (IR[1]=='M'))
	{
		System.out.println(tabs+"W M "+IR[2]+" "+IR[3]);
		intNumber = mem.write(IR[3],p.reg[IR[2]], p);
		p.PC++;
		if(intNumber < 0)
			intNumber = ILEGAL_ACESS;
    }
	else
	if ((IR[0]=='S') && (IR[1]=='U'))
    {
		System.out.println(tabs+"S U "+IR[2]+" "+IR[3]);
		p.reg[IR[2]] = p.reg[IR[2]] - p.reg[IR[3]];
		p.PC++;
    }
	else
	if ((IR[0]=='A') && (IR[1]=='D'))
	{
	    System.out.println(tabs+"A D "+IR[2]+" "+IR[3]);
	    p.reg[IR[2]] = p.reg[IR[2]] + p.reg[IR[3]];
	    p.PC++;
	}
	else
	if ((IR[0]=='D') && (IR[1]=='E') && (IR[2]=='C'))
	{
		System.out.println(tabs+"D E C "+IR[3]);
	    p.reg[IR[3]] = p.reg[IR[3]] - 1;
	    p.PC++;
	}
	else
	if ((IR[0]=='I') && (IR[1]=='N') && (IR[2]=='C'))
	{
		System.out.println("tabs+I N C "+IR[3]);
	    p.reg[IR[3]] = p.reg[IR[3]] + 1;
	    p.PC++;
	}
	else
	if ((IR[0]=='C') && (IR[1]=='P'))
	{
	    System.out.println(tabs+"C P "+IR[2]+" "+IR[3]);
	    if (p.reg[IR[2]] == 0) p.flag[p.Z] = 1; else p.flag[p.Z] = 0;
	    if (p.reg[IR[2]] == p.reg[IR[3]]) p.flag[p.E] = 1; else p.flag[p.E] = 0;
	    if (p.reg[IR[2]] < p.reg[IR[3]]) p.flag[p.L] = 1; else p.flag[p.L] = 0;
	    p.PC++;
	}
	else
	if ((IR[0]=='J') && (IR[1]=='P') && (IR[2]=='A'))
	{
		System.out.println(tabs+"J P A "+IR[3]);
	    p.PC=IR[3];
	}
	else
	if ((IR[0]=='J') && (IR[1]=='P') && (IR[2]=='Z'))
	{
	    System.out.println(tabs+"J P Z "+IR[3]);
	    if (p.flag[p.Z] == 1)
	    	p.PC=IR[3];
	    else
	    	p.PC++;
	}
	else
	if ((IR[0]=='J') && (IR[1]=='P') && (IR[2]=='E'))
	{
	    System.out.println(tabs+"J P E "+IR[3]);
	    if (p.flag[p.E] == 1)
	    	p.PC=IR[3];
	    else
	    	p.PC++;
	}
	else
	if ((IR[0]=='J') && (IR[1]=='P') && (IR[2]=='L'))
	{
	    System.out.println(tabs+"J P L "+IR[3]);
	    if (p.flag[p.L] == 1)
	    	p.PC=IR[3];
	    else
	    	p.PC++;
	}
	else
	if (IR[0]=='I' && IR[1]=='N' && IR[2]=='T')
	{
	    System.out.println(tabs+"I N T "+IR[3]);
	    p.PC++;
	    intNumber = IR[3];
	    //hint.set(IR[3]);
	}
	else
	if(IR[0] == 0 && IR[1] == 0 && IR[2] == 0 && IR[3] >= 0)
	{
		System.out.println(tabs+"Not instruction, just DATA "+IR[3]);
		p.PC++;
	}
	else
	{
	    System.err.println(tabs+"????");
	    //hint.set(ILEGAL_INST);
	    intNumber = ILEGAL_INST;
	}
	return intNumber;
  }
}